#ifndef _mov_reader_h_
#define _mov_reader_h_

#include "movinteral.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif


struct mov_memory_buffer_t
{
	uint8_t* ptr;
	uint64_t off;
	uint64_t capacity;
};

static int mov_memory_read(void* param, void* data, uint64_t bytes)
{
	struct mov_memory_buffer_t* ptr;
	ptr = (struct mov_memory_buffer_t*)param;
	if (ptr->off + bytes > ptr->capacity)
		return -1;

	memcpy(data, ptr->ptr + ptr->off, (size_t)bytes);
	ptr->off += bytes;
	return 0;
}

static int mov_memory_write(void* param, const void* data, uint64_t bytes)
{
	struct mov_memory_buffer_t* ptr;
	ptr = (struct mov_memory_buffer_t*)param;
	if (ptr->off + bytes > ptr->capacity)
		return -1;

	memcpy(ptr->ptr + ptr->off, data, (size_t)bytes);
	ptr->off += bytes;
	return 0;
}

static int mov_memory_seek(void* param, int64_t offset)
{
	struct mov_memory_buffer_t* ptr;
	ptr = (struct mov_memory_buffer_t*)param;
	if ((uint64_t)(offset >= 0 ? offset : -offset) > ptr->capacity)
		return -1;
	ptr->off = offset > 0 ? offset : (ptr->capacity+offset);
	return 0;
}

static int64_t mov_memory_tell(void* param)
{
	struct mov_memory_buffer_t* ptr;
	ptr = (struct mov_memory_buffer_t*)param;
	return (int64_t)ptr->off;
}

static inline const struct mov_buffer_t* mov_memory_buffer(void)
{
	static struct mov_buffer_t s_io = {
		mov_memory_read,
		mov_memory_write,
		mov_memory_seek,
		mov_memory_tell,
	};
	return &s_io;
}


/*---------------------------------------------------------------------------
---------------------------------read----------------------------------------
---------------------------------------------------------------------------*/

typedef struct mov_reader_t mov_reader_t;

mov_reader_t* mov_reader_create(const struct mov_buffer_t* buffer, void* param);
void mov_reader_destroy(mov_reader_t* mov);

struct mov_reader_trackinfo_t
{
	void (*onvideo)(void* param, uint32_t track, uint8_t object, int width, int height, const void* extra, size_t bytes);
	void (*onaudio)(void* param, uint32_t track, uint8_t object, int channel_count, int bit_per_sample, int sample_rate, const void* extra, size_t bytes);
	void (*onsubtitle)(void* param, uint32_t track, uint8_t object, const void* extra, size_t bytes);
};

int mov_reader_getinfo(mov_reader_t* mov, struct mov_reader_trackinfo_t *ontrack, void* param);

uint64_t mov_reader_getduration(mov_reader_t* mov);

typedef void (*mov_reader_onread)(void* param, uint32_t track, const void* buffer, size_t bytes, int64_t pts, int64_t dts, int flags);

int mov_reader_read(mov_reader_t* mov, void* buffer, size_t bytes, mov_reader_onread onread, void* param);


typedef void* (*mov_reader_onread2)(void* param, uint32_t track, size_t bytes, int64_t pts, int64_t dts, int flags);

int mov_reader_read2(mov_reader_t* mov, mov_reader_onread2 onread, void* param);


int mov_reader_seek(mov_reader_t* mov, int64_t* timestamp);


/*---------------------------------------------------------------------------
---------------------------------write---------------------------------------
---------------------------------------------------------------------------*/

typedef struct mov_writer_t mov_writer_t;


mov_writer_t* mov_writer_create(const struct mov_buffer_t* buffer, void* param, int flags);
void mov_writer_destroy(mov_writer_t* mov);

int mov_writer_add_audio(mov_writer_t* mov, uint8_t object, int channel_count, int bits_per_sample, int sample_rate, const void* extra_data, size_t extra_data_size);
int mov_writer_add_video(mov_writer_t* mov, uint8_t object, int width, int height, const void* extra_data, size_t extra_data_size);
int mov_writer_add_subtitle(mov_writer_t* mov, uint8_t object, const void* extra_data, size_t extra_data_size);

int mov_writer_write(mov_writer_t* mov, int track, const void* data, size_t bytes, int64_t pts, int64_t dts, int flags);






#ifdef __cplusplus
}
#endif
#endif /* !_mov_reader_h_*/
